package com.choudou5.solr.util.http;

import cn.hutool.core.map.MapUtil;
import com.choudou5.solr.util.JsonUtil;
import com.choudou5.solr.util.StrUtil;
import org.apache.http.*;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Http工具类
 * @author choudou5
 */
public class HttpUtils {

	private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

	private final static String[] USER_AGENT_ARRAY = new String[]{
			"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
			"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
			"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
			"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
			"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
			"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
			"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
			"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
			"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
			"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
			"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
			"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
			"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
			"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
			"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
			"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
			"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
			"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
			"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
			"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
			"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
			"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
			"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
			"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
			"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
			"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
			"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
			"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
			"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"};

	private static final int TIME_OUT = 3000;

	/**
	 * post请求 （5秒超时）
	 * @param url
	 * @param params
	 * @return
	 */
	public static String post(String url, Map<String, Object> params) {
		return post(url, params, TIME_OUT, "UTF-8");
	}

	public static String post(String url, Map<String, Object> params, String chartset) {
		return post(url, params, TIME_OUT, chartset);
	}

	/**
	 * post请求
	 * @param url
	 * @param params
	 * @param timeout
	 * @return
	 */
	public static String post(String url, Map<String, Object> params, int timeout, String chartset) {
		String result = null;
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse httpResponse = null;
		try {
			httpClient = HttpClients.createDefault();
			HttpPost httpPost = new HttpPost(url);
			Integer ranDomNo = new Double(USER_AGENT_ARRAY.length * Math.random()).intValue();
			httpPost.setHeader("User-Agent", USER_AGENT_ARRAY[ranDomNo]);
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
			httpPost.setConfig(requestConfig);
			if (params != null && params.size() > 0) {
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
				for (Map.Entry<String, Object> entry : params.entrySet()) {
					nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue() == null ? "" : entry.getValue().toString().trim()));
				}
				HttpEntity httpEntity = new UrlEncodedFormEntity(nameValuePairs, chartset);
				if (httpEntity != null) {
					httpPost.setEntity(httpEntity);
				}
			}
			httpResponse = httpClient.execute(httpPost);
			if (httpResponse.getEntity() != null) {
				result = EntityUtils.toString(httpResponse.getEntity(), chartset);
			}
		} catch (Exception e) {
			logger.error("post", e);
		} finally {
			HttpClientUtils.closeQuietly(httpResponse);
			HttpClientUtils.closeQuietly(httpClient);
		}
		return result;
	}

	public static String postSSL(String url, Map<String, Object> params, String chartset) {
		String result = null;
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse httpResponse = null;
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = {new MyX509TrustManager()};
			SSLContext sslContext = SSLContext.getInstance("SSL"); //, "SunJSSE"  TLS
			sslContext.init(null, tm, new java.security.SecureRandom());
			SSLSocketFactory ssf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

			httpClient = HttpClients.custom().setSSLSocketFactory(ssf).build();
			HttpPost httpPost = new HttpPost(url);
			Integer ranDomNo = new Double(USER_AGENT_ARRAY.length * Math.random()).intValue();
			httpPost.setHeader("User-Agent", USER_AGENT_ARRAY[ranDomNo]);
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIME_OUT).setConnectTimeout(TIME_OUT).build();
			httpPost.setConfig(requestConfig);
			if (params != null && params.size() > 0) {
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
				for (Map.Entry<String, Object> entry : params.entrySet()) {
					nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue() == null ? "" : entry.getValue().toString().trim()));
				}
				HttpEntity httpEntity = new UrlEncodedFormEntity(nameValuePairs, chartset);
				if (httpEntity != null) {
					httpPost.setEntity(httpEntity);
				}
			}

			httpResponse = httpClient.execute(httpPost);
			if (httpResponse.getEntity() != null) {
				result = EntityUtils.toString(httpResponse.getEntity(), chartset);
			}
		} catch (Exception e) {
			logger.error("postSSL", e);
		} finally {
			HttpClientUtils.closeQuietly(httpResponse);
			HttpClientUtils.closeQuietly(httpClient);
		}
		return result;
	}


	public static String get(String url) {
		return get(url, "UTF-8");
	}

	/**
	 * get请求 （5秒超时）
	 * @param url
	 * @return
	 */
	public static String get(String url, String charset) {
		String result = null;
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse httpResponse = null;
		try {

			BasicHttpProcessor httpProcessor = new BasicHttpProcessor();
			httpProcessor.addInterceptor(contentEncodingFixerInterceptor);
			httpClient = HttpClients.custom().setHttpProcessor(httpProcessor).build();
//			httpClient = HttpClients.createDefault();
			HttpGet httpGet = new HttpGet(url);
			httpGet.setHeader("Content-Type","text/html; charset=utf-8");
			httpGet.setHeader(HTTP.CONTENT_ENCODING, "identity");
			httpGet.setHeader("connection", "keep-alive");
			Integer ranDomNo = new Double(USER_AGENT_ARRAY.length * Math.random()).intValue();
			httpGet.setHeader("User-Agent", USER_AGENT_ARRAY[ranDomNo]);
			httpGet.setHeader("accept-language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
			httpGet.setHeader("Cache-Control", "no-cache");
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIME_OUT).setConnectTimeout(TIME_OUT).build();
			httpGet.setConfig(requestConfig);
			httpResponse = httpClient.execute(httpGet);
			if (httpResponse.getEntity() != null) {
				result = EntityUtils.toString(httpResponse.getEntity(), charset);
			}
		} catch (Exception e) {
			logger.error("get "+url, e);
			return null;
		} finally {
			HttpClientUtils.closeQuietly(httpResponse);
			HttpClientUtils.closeQuietly(httpClient);
		}
		return result;
	}

	private static HttpResponseInterceptor contentEncodingFixerInterceptor = new HttpResponseInterceptor()  {
		@Override
		public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
			Header contentEncodingHeader = response.getFirstHeader(HTTP.CONTENT_ENCODING);
			if(contentEncodingHeader != null && contentEncodingHeader.getValue().equalsIgnoreCase("none")) {
				response.removeHeaders(HTTP.CONTENT_ENCODING);
				response.addHeader(HTTP.CONTENT_ENCODING, "identity");
			}
		}
	};

	
	public static String getProxy(String url, String proxyIp, int port) {
		String result = null;
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse httpResponse = null;
		try {
			httpClient = HttpClients.createDefault();
			HttpGet httpGet = new HttpGet(url);
			httpGet.setHeader("Content-Type","text/html,application/json; charset=utf-8");
			httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
			httpGet.setHeader("Cache-Control", "no-cache");
			HttpHost proxy = new HttpHost(proxyIp, port);
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIME_OUT).setConnectTimeout(TIME_OUT).setProxy(proxy).build();
			httpGet.setConfig(requestConfig);
			httpResponse = httpClient.execute(httpGet);
			if (httpResponse.getEntity() != null) {
				result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
			}
		} catch (Exception e) {
			logger.error("getProxy", e);
			return null;
		} finally {
			HttpClientUtils.closeQuietly(httpResponse);
			HttpClientUtils.closeQuietly(httpClient);
		}
		return result;
	}
	
	public static String getFromJs(String url){	
		HttpURLConnection con = null;
		try {
			URL u = new URL(url);
			con = (HttpURLConnection) u.openConnection();
			con.setRequestMethod("GET");
			con.setDoOutput(true);
			con.setDoInput(true);
			con.setUseCaches(false);
		} catch (Exception e) {
			logger.error("getFromJs", e);
			return null;
		} finally {
			if (con != null) {
				con.disconnect();
			}
		}

		StringBuilder buffer = new StringBuilder();
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
			String temp = null;
			while ((temp = br.readLine()) != null) {
				buffer.append(temp);
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
			return null;
		}
		return buffer.toString();
	}
	
	public static <T extends Serializable> T postJson(String url, Map<String, Object> params, Class<T> classz) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse httpResponse = null;
		try {
			httpClient = HttpClients.createDefault();
			HttpPost httpPost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIME_OUT).setConnectTimeout(TIME_OUT).build();
			httpPost.setConfig(requestConfig);
			StringEntity entity = new StringEntity(JsonUtil.toStr(params), Consts.UTF_8);
			entity.setContentType("application/json");
			httpPost.setEntity(entity);
			httpResponse = httpClient.execute(httpPost);
			if (httpResponse.getEntity() != null) {
				String result = EntityUtils.toString(httpResponse.getEntity());
				if(result != null){
					return JsonUtil.toJavaObj(result, classz);
				}
			}
		} catch (Exception e) {
			logger.error("postJson", e);
		}finally {
			HttpClientUtils.closeQuietly(httpResponse);
			HttpClientUtils.closeQuietly(httpClient);
		}
		return null;
	}


	public static String postJson(String url, String jsonBody, Map<String, String> headers, String chartset) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse httpResponse = null;
		try {
			httpClient = HttpClients.createDefault();
			HttpPost httpPost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIME_OUT).setConnectTimeout(TIME_OUT).build();
			httpPost.setConfig(requestConfig);
			if(MapUtil.isNotEmpty(headers)){
				for (Map.Entry<String, String> entry : headers.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue());
				}
			}
			StringEntity entity = new StringEntity(jsonBody, chartset);
			entity.setContentType("application/json;");
			httpPost.setEntity(entity);
			httpResponse = httpClient.execute(httpPost);
			if (httpResponse.getEntity() != null) {
				String result = EntityUtils.toString(httpResponse.getEntity(), chartset);
				return result;
			}
		} catch (Exception e) {
			logger.error("postJson", e);
		}finally {
			HttpClientUtils.closeQuietly(httpResponse);
			HttpClientUtils.closeQuietly(httpClient);
		}
		return null;
	}


	/**
	 * 根据url提取url的参数
	 * @param url
	 * @return
	 */
	public static Map<String, String> getUrlParams(String url) {
		Map<String, String> result = new HashMap<>();
		if (url.contains("?")) {
			String paramsStr = url.substring(url.indexOf("?") + 1);
			String[] paramArr = paramsStr.split("&");
			for (String nameValPairStr : paramArr) {
				if (nameValPairStr.contains("=")) {
					String[] nameValPair = nameValPairStr.split("=");
					if (nameValPair.length > 1) {
						result.put(nameValPair[0], nameValPair[1]);
					} else if (nameValPair.length > 0) {
						result.put(nameValPair[0], "");
					}
				}
			}
		}
		return result;
	}
	
	public static void main(String[] args) throws Exception {
		//http
		String url = "http://you.163.com/item/detail?id=1416029";
		String resp = get(url);
		int start = resp.indexOf("JSON_DATA_FROMFTL");
		if(start != -1){
			int end = resp.indexOf("//其他数据")-2;
			System.out.println(StrUtil.sub(resp, start+20, end));
		}else{
			System.out.println(resp);
		}

//		//https
//		url = "https://www.25pp.com/news/user/index";
//		System.out.println(get(url));
	}
	
}
